'''
ftp文件服务器
for server训练
'''
from socket import *
import os,sys
from threading import Thread
import time 

#全局变量
Host = '0.0.0.0'
Port = 8080
Addr = (Host,Port)
File_dir = '/home/tarena/1809/'

#处理僵尸进程
def zombie():
    os.wait()
    
#具体功能实现
class FtpSever(object):
    def __init__(self,connfd):
        self.connfd = connfd

    def do_list(self):
        #获取文件列表
        file_list = os.listdir(File_dir)
        if not file_list:
            self.connfd.send('文件库为空'.encode())
            return
        else:
            self.connfd.send(b'ok')
            time.sleep(0.1)
        for file in file_list:
            if file[0] != '.' and os.path.isfile(File_dir + file):
                self.connfd.send(file.encode())
                time.sleep(0.1)
        self.connfd.send(b'##')
            
    def do_get(self,filename):
        try:
            fr = open(File_dir+filename,'rb')    
        except:
            self.connfd.send('文件不存在'.encode())
            return
        else:
            self.connfd.send(b'ok')
            time.sleep(0.1)
            #发送文件内容
        while True:
            data = fr.read(1024)
            if not data:
                time.sleep(0.1)
                self.connfd.send(b'##')
                break
            self.connfd.send(data)

    def do_put(self,filename):
        try:
            fw = open(File_dir+filename,'wb')
        except:
            self.connfd.send('上传失败'.encode())
            return
        else:
            self.connfd.send(b'ok')
        while True:
            data = self.connfd.recv(1024)
            if data == b'##':
                break
            fw.write(data)
        fw.close()
#创建网络连接
def main():
    s = socket()
    s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
    s.bind(Addr)
    s.listen(5)

    print('Listen to the port 8080...')
    while True:
        try:
            connfd,addr = s.accept()
        except KeyboardInterrupt:
            s.close()
            sys.exit('服务器退出')
        except Exception as e:
            print('服务器异常:',e)
            continue
        print('连接用户:',addr)

        #创建子进程
        pid = os.fork()
        if pid == 0:
            s.close()

            ftp = FtpSever(connfd)
            #循环接手客户端请求
            while True:
                data = connfd.recv(1024).decode()
                if not data or data[0] == 'Q':
                    connfd.close()
                    sys.exit('客户端退出')
                elif data[0] == 'L':
                    ftp.do_list()
                elif data[0] == 'G':
                    filename = data.split(' ')[-1]
                    ftp.do_get(filename)
                elif data[0] == 'P':
                    filename = data.split(' ')[-1]
                    ftp.do_put(filename)

            os._exit(0)
        else:
            connfd.close()
            #单独创建线程处理僵尸进程
            t = Thread(target=zombie)
            t.setDaemon(True)
            t.start()
            continue
main()